package lwq

import (
	"bytes"
	"crypto/aes"
	"crypto/cipher"
	"crypto/md5"
	"encoding/base64"
	"fmt"
)

type JY_校验 struct {
}

func (*JY_校验) Md5_32位校验(校验内容 any, 是否大写 ...bool) (返回值 string) {
	校验文本 := 全_文本.DWB_到文本(校验内容)
	返回值 = fmt.Sprintf("%x", md5.Sum([]byte(校验文本)))
	if len(是否大写) > 0 && 是否大写[0] {
		返回值 = 全_文本.DDX_到大写(返回值)
	}
	return
}
func (类 *JY_校验) JJM_加减密_lwq(加减密文本 string, 密钥 any, 是否为加密 bool) (返回值 string) {
	新密钥 := 类.Md5_32位校验(密钥, true)
	if 是否为加密 {
		返回值 = 加密(加减密文本, 新密钥)
	} else {
		返回值 = 解密(加减密文本, 新密钥)
	}

	return
}

// 密钥 长度必须 16/24/32长度
func 加密(被加密文本 string, 密钥 string) string {
	// 转成字节数组
	origData := []byte(被加密文本)
	k := []byte(密钥)
	// 分组秘钥
	block, err := aes.NewCipher(k)
	if err != nil {
		panic(fmt.Sprintf("密钥 长度必须 16/24/32长度: %s", err.Error()))
	}
	// 获取秘钥块的长度
	blockSize := block.BlockSize()
	// 补全码
	origData = pkCS7Padding(origData, blockSize)
	// 加密模式
	blockMode := cipher.NewCBCEncrypter(block, k[:blockSize])
	// 创建数组
	cryted := make([]byte, len(origData))
	// 加密
	blockMode.CryptBlocks(cryted, origData)
	//使用RawURLEncoding 不要使用StdEncoding
	//不要使用StdEncoding  放在url参数中回导致错误
	return base64.RawURLEncoding.EncodeToString(cryted)

}

// 密钥 长度必须 16/24/32长度
func 解密(被解密文本 string, 密钥 string) string {
	//使用RawURLEncoding 不要使用StdEncoding
	//不要使用StdEncoding  放在url参数中回导致错误
	crytedByte, _ := base64.RawURLEncoding.DecodeString(被解密文本)
	k := []byte(密钥)
	if len(crytedByte) == 0 {
		return ""
	} else if len(crytedByte)%16 != 0 && len(crytedByte)%24 != 0 && len(crytedByte)%32 != 0 {
		return ""
	}

	// 分组秘钥
	block, err := aes.NewCipher(k)
	if err != nil {
		panic(fmt.Sprintf("密钥 长度必须 16/24/32长度: %s", err.Error()))
	}
	// 获取秘钥块的长度
	blockSize := block.BlockSize()
	// 加密模式
	blockMode := cipher.NewCBCDecrypter(block, k[:blockSize])
	// 创建数组
	orig := make([]byte, len(crytedByte))
	// 解密
	blockMode.CryptBlocks(orig, crytedByte)
	// 去补全码
	orig = pkCS7UnPadding(orig)
	return string(orig)
}

// 补码
func pkCS7Padding(ciphertext []byte, blocksize int) []byte {
	padding := blocksize - len(ciphertext)%blocksize
	padtext := bytes.Repeat([]byte{byte(padding)}, padding)
	return append(ciphertext, padtext...)
}

// 去码
func pkCS7UnPadding(origData []byte) []byte {
	length := len(origData)
	unpadding := int(origData[length-1])
	return origData[:(length - unpadding)]
}
